<template>
    <div></div>
</template>
<script>
import { ScreenSpaceEventHandler, ScreenSpaceEventType, Cartesian3 } from "cesium";
import CameraController from '@/cesium/camera-controller';
import { MyCesiumConsts } from '@/constant';
import ClippingBoxManager from "@/cesium/clipping-box-manager";

export default {
    name: 'InnerCamera',
    props: {
        entranceCameraHpr: {
            type: Object
        },
        floorHeight: {
            type: Number
        }
    },
    data() {
        return {
            handlerInstance: null,
            custMouse: {
                rotating: false,
                startPosition: new Cartesian3(),
                preMousePosition: new Cartesian3(),
            },
            custKeyboard: {
                forward: false,
                back: false,
                left: false,
                right: false,
            },
        }
    },
    computed: {
        keyboardChangeStatus() {
            return this.custKeyboard.forward || this.custKeyboard.back || this.custKeyboard.left || this.custKeyboard.right;
        },
    },
    mounted() {
        console.log('---------正在切换相机模式---------');
        this.initCustomCamera();
    },
    beforeDestroy() {
        console.log('---------正在复原相机模式---------');
        const viewer = window.viewer.viewerInstance;
        if (viewer && viewer !== null) {
            const _handler = this.handlerInstance;
            // remove custom mouse events
            if (_handler && _handler !== null) {
                _handler.removeInputAction(ScreenSpaceEventType.LEFT_DOWN);
                _handler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE);
                _handler.removeInputAction(ScreenSpaceEventType.LEFT_UP);
            }
            // remove custom keyboard events
            document.removeEventListener('keydown', this.createKeyDownListener);
            document.removeEventListener('keyup', this.createKeyUpListener);

            // remove clock tick listener
            viewer.clock.onTick.removeEventListener(this.createClockTickListener);

            // release the control of default operations
            CameraController.setCameraInputStatus(true);
        }
    },
    methods: {
        initCustomCamera() {
            const viewer = window.viewer.viewerInstance;
            if (viewer && viewer !== null) {
                // stop default camera operation
                CameraController.setCameraInputStatus(false);
                // using left mouse button to rotate
                this.setMouseHandler(viewer.canvas);
                // using w, a, s, d on keyboard to move
                this.setKeyboardHandler();
                // using the virtual clock to listen on every tick
                this.setClockTickListener(viewer);
            }
        },
        setMouseHandler(canvas) {
            // dispatch the action into three stage
            // the cartesian position shows the position of canvas, but not on the 3d map
            const handler = new ScreenSpaceEventHandler(canvas);
            handler.setInputAction(movement => {
                this.custMouse.rotating = true;
                this.custMouse.preMousePosition = this.custMouse.startPosition = Cartesian3.clone(movement.position);
            }, ScreenSpaceEventType.LEFT_DOWN);

            handler.setInputAction(movement => {
                this.custMouse.preMousePosition = movement.endPosition;
            }, ScreenSpaceEventType.MOUSE_MOVE);
            
            handler.setInputAction(movement => {
                this.custMouse.rotating = false;
            }, ScreenSpaceEventType.LEFT_UP);

            this.handlerInstance = handler;
        },
        setKeyboardHandler() {
            // listen when the keyboard is pressed
            document.addEventListener('keydown', this.createKeyDownListener, false);
            // listen when the keyboard is released
            document.addEventListener('keyup', this.createKeyUpListener, false);
        },
        createKeyDownListener(e) {
            const code = this.checkKeyCode(e.key);
            if (code && code !== null) {
                this.custKeyboard[code] = true;
            }
        },
        createKeyUpListener(e) {
            const code = this.checkKeyCode(e.key);
            if (code && code !== null) {
                this.custKeyboard[code] = false;
                this.custKeyboard.keyChange = false;
            }
        },
        checkKeyCode(key) {
            switch (key) {
                case 'w':
                    return 'forward';
                case 'a':
                    return 'left'
                case 's': 
                    return 'back';  
                case 'd':    
                    return 'right';
                default:
                    return undefined;    
            }
        },
        setClockTickListener(viewer) {
            if (viewer && viewer !== null) {
                viewer.clock.onTick.addEventListener(this.createClockTickListener);
            }
        },
        createClockTickListener() {
            const viewer = window.viewer.viewerInstance;
            if (viewer && viewer !== null) {
                const canvas = viewer.canvas;
                const camera = viewer.camera;
                
                if (this.custMouse.rotating) {
                    // if just rotate, don't need to adjust clipping box
                    // control the camera to rotate if the user is using the mouse to move
                    const width = canvas.clientWidth;
                    const height = canvas.clientHeight;
                    const startPosition = this.custMouse.startPosition;
                    const endPosition = this.custMouse.preMousePosition;

                    const xDistance = (endPosition.x - startPosition.x) / width;
                    const yDistance = -(endPosition.y - startPosition.y) / height;
                    // adjust camera orientation
                    camera.lookRight(xDistance * 0.05);
                    camera.lookUp(yDistance * 0.05);
                }

                if (this.keyboardChangeStatus) {
                    const primitives = viewer.scene.primitives;
                    const innerTileset = primitives.get(primitives.length - 1);

                    // fix and correct the pitch angle to avoid strange camera view
                    // this.correctHprDegree(camera);

                    // defaultMoveAmount: 100000.0
                    const defaultMoveFactor = MyCesiumConsts.CUSTOM_CAMERA_MOVING_FACTOR;
                    if (this.custKeyboard.forward) {
                        camera.moveForward(defaultMoveFactor);
                    }
    
                    if (this.custKeyboard.back) {
                        camera.moveBackward(defaultMoveFactor);
                    }
    
                    if (this.custKeyboard.left) {
                        camera.moveLeft(defaultMoveFactor);
                    }
    
                    if (this.custKeyboard.right) {
                        camera.moveRight(defaultMoveFactor);
                    }

                    const newCameraPosition = camera.position;
                    ClippingBoxManager.adjustClippingBoxAroundCamera(innerTileset, newCameraPosition, this.floorHeight);
                    
                }

            }
        },
        correctHprDegree(camera) {
            const pitchRadianDiff = this.entranceCameraHpr.pitch - camera.pitch
            if (Math.abs(pitchRadianDiff) > 1e-6) {
                // user has changed the pitch orientation
                camera.lookUp(pitchRadianDiff);
            }
        }
    }
}
</script>